package com.jrx.anytxn.investor.handler.impl;

import com.jrx.anytxn.common.exception.TxnBizException;
import com.jrx.anytxn.common.uitl.InternetUtils;
import com.jrx.anytxn.common.uitl.JsonUtils;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.customer.dto.customer.CustomerFirstLevelRes;
import com.jrx.anytxn.customer.dto.customer.CustomerRes;
import com.jrx.anytxn.customer.dto.customer.CustomerSecondLevelRes;
import com.jrx.anytxn.customer.service.ICustomerService;
import com.jrx.anytxn.feign.gateway.bean.ApiResponse;
import com.jrx.anytxn.feign.gateway.request.PartnerRequest02;
import com.jrx.anytxn.feign.gateway.response.PartnerResponse02;
import com.jrx.anytxn.feign.gateway.service.IInnerGatewayService;
import com.jrx.anytxn.feign.param.request.HandleInvestorLimitReq;
import com.jrx.anytxn.feign.param.response.HandleInvestorLimitRes;
import com.jrx.anytxn.feign.param.service.IAnyTxnParamService;
import com.jrx.anytxn.i18n.response.TxnRespResult;
import com.jrx.anytxn.investor.bean.InvestorCreditBean;
import com.jrx.anytxn.investor.constant.TransBizConstant;
import com.jrx.anytxn.investor.entity.TlCustomerInvestorLimit;
import com.jrx.anytxn.investor.entity.TlInvestorLimitApproveLog;
import com.jrx.anytxn.investor.handler.IInvestorCreditHandler;
import com.jrx.anytxn.investor.mapper.ext.ExtTlCustomerInvestorLimitMapper;
import com.jrx.anytxn.investor.mapper.ext.ExtTlInvestorLimitApproveLogMapper;
import com.jrx.anytxn.investor.service.IInvestorCustomerLimitService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.dto.investor.FundTableRes;
import com.jrx.anytxn.param.entity.PrFundFactor;
import com.jrx.anytxn.param.entity.PrInvestorTable;
import com.jrx.anytxn.param.entity.PrProductFund;
import com.jrx.anytxn.param.service.investor.IFundTableService;
import com.jrx.anytxn.param.service.investor.IPrInvestorTableService;
import com.jrx.anytxn.param.service.product.IProductTableService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 联合贷授信实现
 *
 * @author liuyang
 * @date 2020-06-09
 */
@Service
public class InvestorCreditHandlerImpl implements IInvestorCreditHandler {

    private static final Logger logger = LoggerFactory.getLogger(InvestorCreditHandlerImpl.class);

    @Autowired
    private IProductTableService productTableService;

    @Autowired
    private IFundTableService fundTableService;

    @Autowired
    private IPrInvestorTableService investorTableService;

    @Autowired
    private IInvestorCustomerLimitService investorCustomerLimitService;

    @Lazy
    @Autowired
    private IAnyTxnParamService anyTxnParamService;

    @Resource
    private ExtTlCustomerInvestorLimitMapper customerInvestorLimitMapper;

    @Resource
    private ExtTlInvestorLimitApproveLogMapper investorLimitApproveLogMapper;

    @Lazy
    @Autowired
    private IInnerGatewayService innerGatewayService;

    @Autowired
    private ICustomerService customerService;

    /**
     * 联合贷授信
     *
     * @param investorCreditBeans 联合贷授信bean
     * @throws Exception
     * @author liuyang
     * @date 2020-06-09
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public void investorCredit(List<InvestorCreditBean> investorCreditBeans) throws Exception {

        // 初始化数据
        List<TlCustomerInvestorLimit> customerInvestorLimits = new ArrayList<>();
        List<TlInvestorLimitApproveLog> investorLimitApproveLogs = new ArrayList<>();
        CustomerRes customerRes = null;

        for (InvestorCreditBean investorCreditBean : investorCreditBeans) {
            String tenantId = investorCreditBean.getTenantId();
            String investorId = null;
            String productId = investorCreditBean.getProductId();
            String channel = investorCreditBean.getChannel();
            String customerId = investorCreditBean.getCustomerId();

            // 根据产品ID获取资金源list
            List<PrProductFund> productFunds = productTableService.findFundByProductId(productId, tenantId);
            List<String> fundIds = productFunds.stream().map(e -> e.getFundId()).collect(Collectors.toList());

            // 获取客户信息
            if (customerRes == null) {
                customerRes = customerService.getCustomerByChannelAndCustomerIdAndTensnId(channel, customerId, tenantId);
            }

            // 获取资金源list
            List<PrFundFactor> fundFactors = fundTableService.findByFundIdsAndTenId(fundIds, tenantId);
            for (PrFundFactor fundFactor : fundFactors) {
                investorId = fundFactor.getInvestorId();
                // 去除本行
                if (TransBizConstant.BANK_INVESTOR_ID.equals(investorId)) {
                    continue;
                }

                // 获取资金源信息
                FundTableRes fundTableRes = fundTableService.findByFundIdAndTenId(tenantId, fundFactor.getFundId());

                // 获取出资方信息
                PrInvestorTable investorTable = investorTableService.findInvestorByInvestorId(investorId, tenantId);

                // 如果资金源状态为不正常则跳过
                if (!TransBizConstant.STATUS_1.equals(fundTableRes.getTableStatus())) {
                    logger.error("资金源[{}],状态失效",fundFactor.getFundId());
                    if(TransBizConstant.CREDIT_APPROVE_FLAG_2.equals(investorTable.getCreditApproveFlag())){
                        // 创建客户出资方授信审批记录
                        TlInvestorLimitApproveLog investorLimitApproveLog = investorCustomerLimitService.buildInvestorLimitApproveLog(investorCreditBean, investorId, customerRes, TransBizConstant.APPROVE_STATUS_F);
                        investorLimitApproveLogs.add(investorLimitApproveLog);
                    }
                    continue;
                }

                // 如果出资方状态为不正常则跳过
                if (!TransBizConstant.STATUS_1.equals(investorTable.getTableStatus())) {
                    logger.error("出资方[{}],状态失效",investorId);
                    if(TransBizConstant.CREDIT_APPROVE_FLAG_2.equals(investorTable.getCreditApproveFlag())){
                        // 创建客户出资方授信审批记录
                        TlInvestorLimitApproveLog investorLimitApproveLog = investorCustomerLimitService.buildInvestorLimitApproveLog(investorCreditBean, investorId, customerRes, TransBizConstant.APPROVE_STATUS_F);
                        investorLimitApproveLogs.add(investorLimitApproveLog);
                    }
                    continue;
                }

                // 占用授信额度
                HandleInvestorLimitReq req = new HandleInvestorLimitReq(tenantId, investorCreditBean.getSeqNo(), channel,
                        investorId, productId, investorCreditBean.getLimitAmount(), Constant.INVESTOR_LIMIT_CREDITTYPE_C, Constant.INVESTOR_LIMIT_USETYPE_U);
                TxnRespResult<HandleInvestorLimitRes> txnResp = anyTxnParamService.handleInvestorLimit(req);
                if (txnResp == null || TransBizConstant.GATEWAY_SUC!=txnResp.getCode() || !TransBizConstant.USE_RESULT_S.equals(txnResp.getData().getUseResult())) {
                    logger.error("出资方[{}],授信额度占用异常：{}",investorId, JsonUtils.toJSon(txnResp));
                    if(TransBizConstant.CREDIT_APPROVE_FLAG_2.equals(investorTable.getCreditApproveFlag())){
                        // 创建客户出资方授信审批记录
                        TlInvestorLimitApproveLog investorLimitApproveLog = investorCustomerLimitService.buildInvestorLimitApproveLog(investorCreditBean, investorId, customerRes, TransBizConstant.APPROVE_STATUS_F);
                        investorLimitApproveLogs.add(investorLimitApproveLog);
                    }
                    continue;
                }

                // 无需审批
                if (TransBizConstant.CREDIT_APPROVE_FLAG_1.equals(investorTable.getCreditApproveFlag())) {
                    // 构建客户资金源授信额度
                    TlCustomerInvestorLimit customerInvestorLimit = investorCustomerLimitService.buildCustomerInvestorLimit(investorCreditBean, investorId);
                    customerInvestorLimits.add(customerInvestorLimit);
                } else {
                    // 需要审批
                    // 调用task授信结果查询，汇总风控信息 TODO

                    // 创建客户出资方授信审批记录
                    TlInvestorLimitApproveLog investorLimitApproveLog = investorCustomerLimitService.buildInvestorLimitApproveLog(investorCreditBean, investorId, customerRes, "");
                    // 调用出资方（合作行）授信申请接口
                    PartnerRequest02 req02 = this.buildPartnerRequest02(investorCreditBean, investorTable, customerRes, investorLimitApproveLog.getSeqNo());
                    ApiResponse<PartnerResponse02> resp = innerGatewayService.partnerCreditApply(JsonUtils.toJSon(req02));
                    if (resp==null || TransBizConstant.GATEWAY_SUC!=resp.getCode()) {
                        logger.error("出资方[{}],授信审批异常：{}",investorId, JsonUtils.toJSon(resp));
                    }

                    // 获取出资方授信审批状态和授信流水号
                    String approveStatus = "";
                    String creditSeq = "";
                    if(resp!=null && resp.getData()!=null){
                        if(StringUtils.isNotEmpty(resp.getData().getApproveStatus())){
                            approveStatus = resp.getData().getApproveStatus();
                        }
                        creditSeq = resp.getData().getCreditSeq();
                    }

                    // 更新出资方授信审批记录
                    investorLimitApproveLog.setApproveStatus(approveStatus);// 审批状态
                    investorLimitApproveLogs.add(investorLimitApproveLog);

                    // 合作方审批通过则构建客户资金源授信额度
                    if(TransBizConstant.APPROVE_STATUS_S.equals(approveStatus)){
                        TlCustomerInvestorLimit customerInvestorLimit = investorCustomerLimitService.buildCustomerInvestorLimit(investorCreditBean, investorId);
                        customerInvestorLimits.add(customerInvestorLimit);
                    }

                    // 合作方审批拒绝则恢复出资方授信额度
                    if(!TransBizConstant.APPROVE_STATUS_S.equals(approveStatus)&&!TransBizConstant.APPROVE_STATUS_O.equals(approveStatus)){
                        req = new HandleInvestorLimitReq(tenantId, investorCreditBean.getSeqNo(), investorCreditBean.getChannel(),
                                investorId, productId, investorCreditBean.getLimitAmount(), Constant.INVESTOR_LIMIT_CREDITTYPE_C, Constant.INVESTOR_LIMIT_USETYPE_R);
                        txnResp = anyTxnParamService.handleInvestorLimit(req);
                        if (txnResp == null || TransBizConstant.GATEWAY_SUC!=txnResp.getCode() || !TransBizConstant.USE_RESULT_S.equals(txnResp.getData().getUseResult())) {
                            logger.error("出资方[{}],授信额度恢复异常：{}",investorId, JsonUtils.toJSon(txnResp));
                            throw new TxnBizException("出资方授信额度恢复异常");
                        }
                    }
                }
            }
        }

        // 数据保存
        if (CollectionUtils.isNotEmpty(customerInvestorLimits)) {
            customerInvestorLimitMapper.batchInsert(customerInvestorLimits);
        }
        if (CollectionUtils.isNotEmpty(investorLimitApproveLogs)) {
            investorLimitApproveLogMapper.batchInsert(investorLimitApproveLogs);
        }
    }

    /**
     * 构建授信申请请求
     *
     * @param bean 联合贷授信bean
     * @param investorTable 出资方信息
     * @param customerRes 客户信息
     * @param serviceSeq 请求流水号
     * @return PartnerRequest02 授信申请请求实体
     * @throws Exception
     * @author liuyang
     * @date 2020-06-16
     */
    private PartnerRequest02 buildPartnerRequest02(InvestorCreditBean bean, PrInvestorTable investorTable, CustomerRes customerRes, String serviceSeq) throws Exception {

        CustomerFirstLevelRes firstLevel = customerRes.getFirstLevel();
        CustomerSecondLevelRes secondLevel = customerRes.getSecondLevel();

        PartnerRequest02 req = new PartnerRequest02();
        req.setServiceId(TransBizConstant.GATEWAY_SERVICE_ID); // 请求系统Id
        req.setServiceIp(InternetUtils.getLocalIp()); // 请求ip地址
        req.setTenantId(bean.getTenantId()); // 租户Id
        req.setServiceSeq(serviceSeq); // 请求流水号
        req.setInvestorId(investorTable.getInvestorId()); // 出资方ID
        req.setCustNo(bean.getCustomerId()); // 客户号
        req.setProductNo(bean.getProductId()); // 产品号
        req.setName(bean.getChineseName()); // 姓名
        req.setMobile(secondLevel.getMobile()); // 手机号
        req.setIdNumber(firstLevel.getIdNumber()); // 证件号
        req.setIdType(firstLevel.getIdType()); // 证件类型
        req.setIdIssueAgent(firstLevel.getIdIssueAgent()); // 发证机关
        req.setIdEffectiveDate(firstLevel.getIdEffectiveDate()); // 证件有效期起始日期
        req.setIdExpireDate(firstLevel.getIdExpireDate()); // 证件有效期终止日期
        req.setRace(firstLevel.getRace()); // 民族
        req.setSex(firstLevel.getSex()); // 性别
        req.setMaritalStatus(secondLevel.getMaritalStatus()); // 婚姻状态
        req.setEducation(secondLevel.getEducation()); // 学历
        req.setOccuptionType(""); // 职业类型 TODO 公司，联系人，住址是一个list 怎么获取。
        req.setCompanyName(""); // 公司名称
        req.setRelationship(""); // 联系人关系
        req.setContactName(""); // 联系人姓名
        req.setContactMobile(""); // 联系人电话
        req.setLiveAddress(""); // 住址
        req.setContractNumber(bean.getContractNumber()); // 合同号

        return req;
    }
}
